home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / misc / amag / sh9301e.lha / Maxon-CPP-Demo / MSDB / demo / fclass.c next >
C/C++ Source or Header  |  1993-02-17  |  6KB  |  331 lines

  1. /*
  2.   Funktionsplotter in Maxon C++
  3.  
  4.   Function-Modul
  5.  
  6.   Jens Gelhar 09.11.91
  7. */
  8.  
  9. #include <stream.h>
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include <stdlib.h>
  13. #include <ctype.h>
  14.  
  15. #include "fclass.h"
  16.  
  17. // Destruktoren:
  18.  
  19. Func::~Func() { }       // Default: garnix
  20.  
  21. UnOpN::~UnOpN()
  22.  { delete arg; }
  23.  
  24. BinOpN::~BinOpN()
  25.  { delete l;
  26.    delete r;
  27.  }
  28.  
  29. // Konstruktoren:
  30.  
  31. double Func::Dummy;
  32.  
  33. KonstN::KonstN (double c)
  34.  { Konst = c; }
  35.  
  36. UnOpN::UnOpN(UnOps op, Func *n):
  37.  oper(op), arg(n)
  38. { }
  39.  
  40. BinOpN::BinOpN(BinOps op, Func *ln, Func *rn):
  41.  oper(op), l(ln), r(rn)
  42. { }
  43.  
  44. // "Konstant"-Funktionen:
  45.  
  46. int Func::isconst (double &retval)
  47.   { return 0; }
  48.  
  49. int KonstN::isconst (double &retval)
  50.   { retval = Konst;
  51.     return 1;
  52.   }
  53.  
  54. // Ausgabe
  55.  
  56. #define EPANIC 26731
  57.  
  58. void KonstN::print(char*)
  59.  {
  60.    printf("%g", Konst);
  61.  }
  62.  
  63. void VarN::print(char*)
  64.  { printf("x"); }
  65.  
  66. void ErrorN::print(char*)
  67.  { printf("?"); }
  68.  
  69. void UnOpN::print(char* str)
  70.   { switch(oper)
  71.     { case Op_neg: printf("-"); break;
  72.       case Op_sqr: printf("sqr "); break;
  73.       case Op_sqrt: printf("sqrt "); break;
  74.       case Op_sin: printf("sin "); break;
  75.       case Op_cos: printf("cos "); break;
  76.       case Op_exp: printf("exp "); break;
  77.       case Op_ln:  printf("ln "); break;
  78.     }
  79.     arg->print(str);
  80.   }
  81.  
  82. void BinOpN::print(char* str)
  83.   { printf("(");
  84.     l->print(str);
  85.     switch (oper)
  86.     { case Op_add: printf("+"); break;
  87.       case Op_sub: printf("-"); break;
  88.       case Op_mult:printf("*"); break;
  89.       case Op_div: printf("/"); break;
  90.       case Op_pot: printf("^"); break;
  91.       default: exit(EPANIC);
  92.     }
  93.     r->print(str);
  94.     printf(")");
  95.   }
  96.  
  97. // Auswertung
  98.  
  99. inline double sqr(double x)
  100.   { return x*x; }
  101.  
  102. double intpotz(double base, int exp)
  103.   { if (exp)
  104.       { if (exp<0) return 1.0/intpotz(base,-exp)
  105.         else if (exp==1) return base;
  106.         else if (exp&1) return base*sqr(intpotz(base, exp/2));
  107.                         else return sqr(intpotz(base, exp/2));
  108.        }
  109.      else return 1;
  110.   }
  111.  
  112. double UnOpN::eval (double x)
  113.  {
  114.    double y = arg->eval(x);
  115.  
  116.    switch(oper)
  117.    { case Op_neg:  return -y;
  118.      case Op_sqr:  return y*y;
  119.      case Op_sqrt: return sqrt(y);
  120.      case Op_sin:  return sin(y);
  121.      case Op_cos:  return cos(y);
  122.      case Op_exp:  return exp(y);
  123.      case Op_ln:   return log(y);
  124.      default: exit(EPANIC);
  125.    }
  126. }
  127.  
  128. double BinOpN::eval (double x)
  129.  { double lv = l->eval(x), rv = r->eval(x);
  130.    switch(oper)
  131.    { case Op_add:  return lv+rv;
  132.      case Op_sub:  return lv-rv;
  133.      case Op_mult: return lv*rv;
  134.      case Op_div:  return lv/rv;
  135.      case Op_pot:  if (r->isconst() && floor(rv)==rv)
  136.                      return intpotz(lv, int(rv))
  137.                    else if (lv > 0) return exp(rv*log(lv));
  138.                                     return 0;
  139.      default: exit(EPANIC);
  140.    }
  141.  }
  142.  
  143.  
  144. // ******** Parsing ********
  145.  
  146. #define EULER 2.7182818284
  147. #define PI 3.141592653589
  148.  
  149. char *cp;       // Zeiger auf String
  150. char c;         // gescanntes Zeichen
  151. short ErrFlag;  // Fehler aufgetreten?
  152.  
  153.  
  154. char Get()
  155. { while ((c = *cp) == ' ')
  156.     cp++;
  157.   if(c) cp++;
  158.   return c;
  159. }
  160.  
  161. Func *Fehler()
  162.  { if (!ErrFlag)
  163.      { cout << "\nError.\n";
  164.        ErrFlag = 1;
  165.      }
  166.    return new ErrorN;
  167.  }
  168.  
  169. Func *Expression();
  170.  
  171. Func *Term();
  172.  
  173. Func *Potenz();
  174.  
  175. Func *Factor()
  176. { while (c=='+') Get();
  177.  
  178.   if (c=='x' || c=='X')
  179.     { Get();
  180.       return new VarN;
  181.     }
  182.   else if (c >= '0' && c <= '9')
  183.     {
  184.       int i = 0;
  185.       enum {max = 80};
  186.       char numstr[max+1];
  187.  
  188.       while (isdigit(c) && i<max)
  189.         { numstr[i++] = c; Get(); }
  190.  
  191.       if (c=='.')
  192.         { numstr[i++] = c; Get(); }
  193.       while (isdigit(c) && i<max)
  194.         { numstr[i++] = c; Get(); }
  195.  
  196.       if (tolower(c)=='e')
  197.         { numstr[i++] = c; Get();
  198.  
  199.           if (c=='+' || c=='-')
  200.             { numstr[i++] = c; Get(); }
  201.           else
  202.           if (!isdigit(c))
  203.             return Fehler();
  204.  
  205.           while (isdigit(c) && i<max)
  206.             { numstr[i++] = c; Get(); }
  207.  
  208.         }
  209.  
  210.       numstr[i]=0;
  211.       return new KonstN(atof(numstr));
  212.      }
  213.    else
  214.    if (c=='(')
  215.      { Get();
  216.        Func *np = Expression();
  217.        if (c==')')
  218.          Get();
  219.        else
  220.          delete Fehler();
  221.        return np;
  222.      }
  223.    else
  224.    if (c=='c')
  225.      { if (Get()=='o' && Get() == 's')
  226.          { Get(); return new UnOpN(Op_cos, Factor()); }
  227.        else
  228.          return Fehler();
  229.      }
  230.    else
  231.    if (c=='e')
  232.      { if (Get()!='x')
  233.          return new KonstN(EULER);
  234.        else if (Get() == 'p')
  235.          { Get(); return new UnOpN(Op_exp, Factor()); }
  236.        else
  237.          return Fehler();
  238.      }
  239.    else if (c=='l')
  240.      { if (Get()=='n')
  241.          return Get(), new UnOpN(Op_ln, Factor());
  242.        else
  243.          return Fehler();
  244.      }
  245.    else if (c=='p')
  246.      { if (Get()!='i')
  247.          return Fehler();
  248.        Get(); return new KonstN(PI);
  249.      }
  250.    else if (c=='s')
  251.      { Get();
  252.        if (c=='i')
  253.          { if (Get() != 'n') return Fehler();
  254.            Get();
  255.            return new UnOpN(Op_sin, Factor());
  256.          }
  257.        else if (c=='q')
  258.          { if (Get() != 'r') return Fehler();
  259.            if (Get()=='t')
  260.              { Get();
  261.                return new UnOpN(Op_sqrt, Factor());
  262.              }
  263.            else return new UnOpN(Op_sqr, Factor());
  264.          }
  265.        else
  266.          return Fehler();
  267.      }
  268.  
  269.    // Default-Ergebnis:
  270.    return Fehler();
  271. }
  272.  
  273. Func *Potenz()
  274. {
  275.   Func *n1 = Factor();
  276.  
  277.   while (c=='^')
  278.     { Get();
  279.       Func *n2 = Factor();
  280.       n1 = new BinOpN(Op_pot, n1, n2);
  281.     }
  282.   return n1;
  283. }
  284.  
  285. Func *Term()
  286. { Func *n1 = Potenz();
  287.  
  288.   while (c=='*' || c=='/')
  289.     { BinOps op = c=='*'? Op_mult : Op_div;
  290.       Get();
  291.       Func *n2 = Potenz();
  292.       n1 = new BinOpN(op, n1, n2);
  293.     }
  294.   return n1;
  295. }
  296.  
  297. Func *Expression()
  298. {
  299.   if (c=='-')
  300.    { Get();
  301.      Func *np = Term();
  302.        return new UnOpN(Op_neg,np);
  303.    }
  304.   else
  305.    { Func *n1 = Term();
  306.      while (c=='+' || c=='-')
  307.        { BinOps op = c=='+'? Op_add : Op_sub;
  308.          Get();
  309.          Func *n2 = Term();
  310.          n1 = new BinOpN(op, n1, n2);
  311.        }
  312.      return n1;
  313.    }
  314. }
  315.  
  316. Func *Parse(char *string)
  317. { cp = string;
  318.   ErrFlag = 0;
  319.  
  320.   Get();
  321.   Func *expr = Expression();
  322.   if (c) delete Fehler();
  323.  
  324.   if(ErrFlag)
  325.     { delete expr; return 0; }
  326.   else
  327.     return expr;
  328. }
  329.  
  330.  
  331.